﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ueEngine.Framework.Empires
{
    internal class TempleteBodyAnalyzer : BaseBodyAnalyzer
    {
        #region BuildBody
        public override string Analyzer(string identity, string fileStream, string templetePath)
        {
            string bodyStream = string.Empty;
            Regex reg = new Regex(PageBuilderRegexpLib.BodyPicker);
            if (!reg.IsMatch(fileStream))
            {
                return fileStream;
            }
            bodyStream = reg.Match(fileStream).Groups[0].ToString();
            bodyStream = CorrectionBodySrc(bodyStream, templetePath);
            bodyStream = CorrectionBodyhref(bodyStream, templetePath);
            bodyStream = AnalyzerLabel(bodyStream, identity);
            return bodyStream;
        }
        protected override string FileHTML(string empelement, List<DefaultDataPack> data)
        {
            string modeType = string.Empty;
            var items = FilterSource(empelement).ToList();
            StringBuilder sb = new StringBuilder();
            foreach (var item in items)
            {
                switch (item.Label.labelName.ToLower())
                {
                    case "text":
                        sb.Append(item.Temp);
                        break;
                    case "fill":
                        switch (item.Label.Mode.ToLower())
                        {
                            case "text":
                                sb.Append(GetDataWithModePickerForTextMode(data, 0, item));
                                break;
                            case "repeat":
                                sb.Append(GetDataWithModePickerForRepeatMode(data, item));
                                break;
                            default:
                                return "";
                        }
                        break;
                }
            }
            return sb.ToString();
        }
        protected override IEnumerable<CatchMode> FilterSource(string empelement)
        {
            Regex reg = new Regex(PageBuilderRegexpLib.IgnoreLabel, RegexOptions.IgnoreCase);
            empelement = reg.Replace(empelement, "");//删除ignore节点下所有字符串

            reg = new Regex(PageBuilderRegexpLib.EmpiresInnerText, RegexOptions.IgnoreCase);
            empelement = reg.Match(empelement).Groups[0].ToString(); //剥离empires标签

            Queue<string> queue = new Queue<string>();
            reg = new Regex(PageBuilderRegexpLib.TextOrFillLabel, RegexOptions.IgnoreCase);
            var matchs = reg.Matches(empelement);
            string piece = string.Empty;
            foreach (var match in matchs)
            {
                piece = match.ToString();
                if (String.IsNullOrEmpty(piece))
                {
                    continue;
                }
                queue.Enqueue(piece);
            }
            int count = queue.Count;
            CatchMode mode = null;
            for (int i = 0; i < count; i++)
            {
                mode = new CatchMode();
                piece = queue.Dequeue();
                mode.Label = CatchLabel(piece);
                mode.Temp = CatchLabelInnerText(piece);
                if (mode.Label.labelName == "text")
                {
                    yield return mode;
                }
                else
                {
                    mode.Mode = GetCatchMode(piece);
                    yield return mode;
                }

            }
        }
        protected override string CorrectionBodySrc(string bodyStream, string templetePath)
        {
            Regex reg = new Regex(PageBuilderRegexpLib.SrcPicker, RegexOptions.IgnoreCase);
            MatchCollection matchs = reg.Matches(bodyStream);
            int addindex = 0;
            Regex matching = new Regex("{:\\w+?}", RegexOptions.IgnoreCase);
            foreach (Match item in matchs)
            {
                string path = item.ToString().Replace("/", "\\");
                if (matching.IsMatch(path) || String.IsNullOrEmpty(path))
                {
                    continue;
                }
                if (path.Contains("..")) //如果连接中存在..，则找到其正确的地址
                {
                    List<string> piece = path.Split('\\').ToList();
                    int pevtimes = piece.Where(c => c == "..").Count();
                    System.IO.DirectoryInfo dir = new System.IO.FileInfo(templetePath).Directory;
                    for (int i = 0; i < pevtimes; i++)
                    {
                        dir = dir.Parent;
                    }
                    string currentPath = dir.FullName.EndsWith("\\") ? dir.FullName : dir.FullName + "\\";
                    if (!currentPath.Contains(AppDomain.CurrentDomain.SetupInformation.ApplicationBase))
                    {
                        bodyStream = reg.Replace(bodyStream, "javascript:;", 1, item.Index + addindex);
                        addindex += currentPath.Length - path.Length;
                    }
                    else
                    {
                        currentPath = currentPath.Replace(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "");
                        currentPath += Concat(piece.Where(c => c != "..").ToList());
                        bodyStream = reg.Replace(bodyStream, currentPath.StartsWith("\\") ? currentPath : "\\" + currentPath, 1, item.Index + addindex);
                        addindex += currentPath.Length - path.Length;
                    }
                }
                else
                {
                    System.IO.DirectoryInfo dir = new System.IO.FileInfo(templetePath).Directory;
                    string currentPath = dir.FullName.EndsWith("\\") ? dir.FullName : dir.FullName + "\\";
                    currentPath = currentPath.Replace(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "");
                    if (currentPath.EndsWith("\\"))
                    {
                        if (path.StartsWith("\\"))
                        {
                            currentPath += path.Substring(1);
                        }
                        else
                        {
                            currentPath += path;
                        }
                    }
                    else
                    {
                        if (path.StartsWith("\\"))
                        {
                            currentPath += path;
                        }
                        else
                        {
                            currentPath += "\\" + path;
                        }
                    }
                    bodyStream = reg.Replace(bodyStream, currentPath.StartsWith("\\") ? currentPath : "\\" + currentPath, 1, item.Index + addindex);
                    addindex += currentPath.Length - path.Length;
                }
            }
            return bodyStream;
        }
        protected override string CorrectionBodyhref(string bodyStream, string templetePath)
        {
            Regex reg = new Regex(PageBuilderRegexpLib.AHrefPicker, RegexOptions.IgnoreCase);
            MatchCollection matchs = reg.Matches(bodyStream);
            int addindex = 0;
            string path = string.Empty;  //被捕获字段
            string querystring = string.Empty; //页面传参
            string url = string.Empty; //请求地址
            string action = string.Empty; //请求文件
            string realurl = string.Empty; //实际解析后的地址
            foreach (Match item in matchs)
            {
                path = item.ToString().Replace("/", "\\");
                if (path.IndexOf('?') > 0) //检查是否带有参数
                {
                    querystring = path.Substring(path.IndexOf('?'));
                    url = path.Substring(0, path.IndexOf('?'));
                }
                else
                {
                    querystring = string.Empty;
                    url = path;
                }
                if (url.Contains("\\")) //检测是否在其他目录下
                {
                    action = url.Substring(url.LastIndexOf('\\') + 1, url.LastIndexOf('.') - url.LastIndexOf('\\') - 1);
                }
                else
                {
                    action = url.Substring(0, url.LastIndexOf('.'));
                }
                //生成url
                realurl = "/" + action + querystring;
                bodyStream = reg.Replace(bodyStream, realurl, 1, item.Index + addindex);
                addindex += realurl.Length - path.Length;
            }
            return bodyStream;
        }
        protected override string AnalyzerLabel(string bodyStream, string identity)
        {
            Regex sreg = new Regex(PageBuilderRegexpLib.LabelPick, RegexOptions.IgnoreCase);
            MatchCollection matchs = sreg.Matches(bodyStream);
            int addindex = 0;

            Regex empreg = new Regex(PageBuilderRegexpLib.EmpiresLabel, RegexOptions.IgnoreCase);
            foreach (Match item in matchs)
            {
                string element = item.ToString();
                Match method = empreg.Match(element);
                var name = method.Groups["name"].ToString();

                List<DefaultDataPack> data = new List<DefaultDataPack>();
                string html = string.Empty;
                if (name.ToLower() == "system") //如果为系统预定义函数
                {
                    Regex reg = new Regex(PageBuilderRegexpLib.SysMethodLabel, RegexOptions.IgnoreCase);
                    html = Method.SystemMethod(reg.Match(element).ToString(), identity);
                }
                else
                {
                    data = Method.ReflectionMethod(name, identity);
                    html = FileHTML(element, data);
                }
                bodyStream = sreg.Replace(bodyStream, html, 1, item.Index + addindex);
                addindex += html.Length - element.Length;
            }
            return bodyStream;
        }
        protected override LabelPack CatchLabel(string input)
        {
            Regex reg = new Regex(PageBuilderRegexpLib.LabelCatch, RegexOptions.IgnoreCase);
            var match = reg.Match(input);
            string item = match.Groups["item"].ToString();
            int time = 1;
            if (!String.IsNullOrEmpty(item))
            {
                if (!Int32.TryParse(item, out time))
                {
                    time = 1;
                }
            }
            return new LabelPack()
            {
                labelName = match.Groups["label"].ToString(),
                Mode = match.Groups["mode"].ToString(),
                Item = time
            };
        }
        protected override ModePack GetCatchMode(string input)
        {
            Regex reg = new Regex(PageBuilderRegexpLib.ModeCatch, RegexOptions.IgnoreCase);
            Match matchs = reg.Match(input);
            return new ModePack()
            {
                DefaultVal = matchs.Groups["def"].ToString(),
                Field = matchs.Groups["field"].ToString(),
                Index = matchs.Groups["idx"].ToString(),
                SubString = matchs.Groups["sub"].ToString()
            };
        }
        protected override string CatchLabelInnerText(string input)
        {
            Regex reg = new Regex(PageBuilderRegexpLib.LabelInner, RegexOptions.IgnoreCase);
            return reg.Match(input).Groups["text"].ToString();
        }
        protected override string GetDataWithModePickerForTextMode(List<DefaultDataPack> data, int defrow, CatchMode pack)
        {

            Regex reg = new Regex(PageBuilderRegexpLib.FiledPick, RegexOptions.IgnoreCase);
            var match = reg.Matches(pack.Temp);
            for (int i = 0; i < match.Count; i++)
            {
                var mode = GetCatchMode(match[i].Value);
                int idx = defrow;
                if (Int32.TryParse(mode.Index, out idx))
                {
                    idx = idx < data.Count - 1 ? idx : defrow;
                }
                else
                {
                    idx = defrow;
                }
                DefaultDataPack datarow = null;
                if (data.Count == 0)
                {
                    datarow = new DefaultDataPack();
                }
                else
                {
                    datarow = data[idx];
                }
                var col = datarow.GetType().GetProperty(mode.Field);
                object o_colval = col == null ? null : col.GetValue(datarow, null);
                string colval = o_colval != null ? o_colval.ToString() : String.Empty;
                if (String.IsNullOrEmpty(colval))
                {
                    colval = mode.DefaultVal;
                }
                if (!String.IsNullOrEmpty(mode.SubString))
                {
                    string startStr = mode.SubString.Remove(mode.SubString.IndexOf(','));
                    string endStr = mode.SubString.Substring(mode.SubString.IndexOf(',') + 1);
                    int start = 0;
                    int end = 0;
                    Int32.TryParse(startStr, out start);
                    Int32.TryParse(endStr, out end);
                    int length = colval.Length;
                    start = (start >= 0 && start < length - 1) ? start : 0;
                    end = (end > start && end < length - 1) ? end : length - 1;
                    colval = colval.Substring(start, end - start + 1);
                }
                pack.Temp = pack.Temp.Replace(match[i].Value, colval);
            }
            //处理条件判断where标签
            reg = new Regex(PageBuilderRegexpLib.WhereLabel, RegexOptions.IgnoreCase);
            var expmatch = reg.Matches(pack.Temp);
            if (expmatch.Count > 0) //如果匹配成功
            {
                for (int i = 0; i < expmatch.Count; i++)
                {
                    var x = expmatch[i].Value;
                    string left = expmatch[i].Groups["left"].Value; //获得左表达式
                    string sign = expmatch[i].Groups["sign"].Value; //获得符号
                    string right = expmatch[i].Groups["right"].Value; //获得右表达式
                    int processresult = 1; //1:包含, 0:忽略 默认包含
                    #region 条件判断
                    if (!String.IsNullOrEmpty(left) && !String.IsNullOrEmpty(sign) && !String.IsNullOrEmpty(right))
                    {
                        int rightvalue = 0;
                        int leftvalue = 0;
                        switch (sign)
                        {
                            case ">=":
                                if (Int32.TryParse(right, out rightvalue) && Int32.TryParse(left, out leftvalue))
                                {
                                    if (leftvalue >= rightvalue)
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                break;
                            case "<=":
                                if (Int32.TryParse(right, out rightvalue) && Int32.TryParse(left, out leftvalue))
                                {
                                    if (leftvalue <= rightvalue)
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                break;
                            case ">":
                                if (Int32.TryParse(right, out rightvalue) && Int32.TryParse(left, out leftvalue))
                                {
                                    if (leftvalue > rightvalue)
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                break;
                            case "<":
                                if (Int32.TryParse(right, out rightvalue) && Int32.TryParse(left, out leftvalue))
                                {
                                    if (leftvalue < rightvalue)
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                break;
                            case "==":
                                if (Int32.TryParse(right, out rightvalue) && Int32.TryParse(left, out leftvalue))
                                {
                                    if (leftvalue == rightvalue)
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                else
                                {
                                    if (left.ToLower() == right.ToLower())
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                break;
                            case "!=":
                                if (Int32.TryParse(right, out rightvalue) && Int32.TryParse(left, out leftvalue))
                                {
                                    if (leftvalue != rightvalue)
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                else
                                {
                                    if (left.ToLower() != right.ToLower())
                                    {
                                        processresult = 1;
                                    }
                                    else
                                    {
                                        processresult = 0;
                                    }
                                }
                                break;
                        }
                    }
                    #endregion
                    if (processresult == 0)
                    {
                        pack.Temp = pack.Temp.Replace(expmatch[i].Value, "");
                    }
                    else
                    {
                        pack.Temp = pack.Temp.Replace(expmatch[i].Value, expmatch[i].Groups["content"].Value);
                    }
                }
            }
            return pack.Temp;
        }
        protected override string GetDataWithModePickerForRepeatMode(List<DefaultDataPack> data, CatchMode pack)
        {
            StringBuilder sb = new StringBuilder();
            int repeatTime = Math.Min(data.Count, pack.Label.Item);
            CatchMode packTemp;
            for (int x = 0; x < repeatTime; x++)
            {
                packTemp = CloneCatchMode(pack);
                sb.Append(GetDataWithModePickerForTextMode(data, x, packTemp));
            }
            return sb.ToString();
        }
        protected override CatchMode CloneCatchMode(CatchMode target)
        {
            CatchMode newOne = new CatchMode();
            newOne.Label = new LabelPack();
            newOne.Mode = new ModePack();

            newOne.Label.Item = target.Label.Item;
            newOne.Label.labelName = target.Label.labelName;
            newOne.Label.Mode = target.Label.Mode;
            newOne.Mode.DefaultVal = target.Mode.DefaultVal;
            newOne.Mode.Field = target.Mode.Field;
            newOne.Mode.Index = target.Mode.Index;
            newOne.Mode.SubString = target.Mode.SubString;
            newOne.Temp = target.Temp;
            return newOne;
        }
        #endregion

    }
}
